package com.elite.groovy.dev;

import com.ciphergateway.crypto.CGCipher;

import javax.xml.bind.DatatypeConverter;
import java.util.Arrays;

public class SM4Test {

	public static void main(String[] args) {
		byte[] keys = new byte[]{
			(byte)0xfe, (byte)0xff, (byte)0xe9, (byte)0x92, (byte)0x86, (byte)0x65, (byte)0x73, (byte)0x1c, 
			(byte)0x6d, (byte)0x6a, (byte)0x8f, (byte)0x94, (byte)0x67, (byte)0x30, (byte)0x83, (byte)0x08
		};
		byte[] input = new byte[]{
			(byte)0xd9, (byte)0x31, (byte)0x32, (byte)0x25, (byte)0xf8, (byte)0x84, (byte)0x06, (byte)0xe5, 
			(byte)0xa5, (byte)0x59, (byte)0x09, (byte)0xc5, (byte)0xaf, (byte)0xf5, (byte)0x26, (byte)0x9a
		};
		byte[] iv = new byte[]{
			(byte)0x99, (byte)0xaa, (byte)0x3e, (byte)0x68, (byte)0xed, (byte)0x81, (byte)0x73, (byte)0xa0,
			(byte)0xee, (byte)0xd0, (byte)0x66, (byte)0x84, (byte)0xee, (byte)0xd0, (byte)0x66, (byte)0x84
		};
		byte[] aad = new byte[]{
			(byte)0x4d, (byte)0x23, (byte)0xc3, (byte)0xce, (byte)0xc3, (byte)0x34, (byte)0xb4, (byte)0x9b,
			(byte)0xdb, (byte)0x37, (byte)0x0c, (byte)0x43, (byte)0x7f, (byte)0xec, (byte)0x78, (byte)0xde
		};
		byte[] cipher;
		byte[] plain;
		
		System.out.println("Test Parameter");
		System.out.println(keys.length + " bytes key:" + DatatypeConverter.printHexBinary(keys));
		System.out.println(iv.length + " bytes iv:" + DatatypeConverter.printHexBinary(iv));
		System.out.println(aad.length + " bytes aad:" + DatatypeConverter.printHexBinary(aad));
		System.out.println(input.length + " bytes plain:" + DatatypeConverter.printHexBinary(input));
		System.out.println("=================================================================\n");
		
		
		CGCipher sm4 = CGCipher.getInstance("sm4", "ecb");
		System.out.println("Test SM4 ECB Encrypt & Decrypt");
		cipher = sm4.sm4_encrypt(CGCipher.PKCS_PADDING, input, keys, iv);
		if(cipher == null){
			System.out.println("SM4 ECB Encrypt Faild");
			return;
		}
		System.out.println(cipher.length + " bytes cipher:" + DatatypeConverter.printHexBinary(cipher));
		
		plain = sm4.sm4_decrypt(CGCipher.PKCS_PADDING, cipher, keys, iv);
		if(plain == null){
			System.out.println("SM4 ECB Decrypt Faild");
			return;
		}
		System.out.println(plain.length + " bytes plain:" + DatatypeConverter.printHexBinary(plain));
		System.out.println("SM4 ECB Encrypt & Decrypt Test SUCCESS");
		System.out.println("=================================================================\n");
		
		
		sm4 = CGCipher.getInstance("sm4", "cbc");
		System.out.println("Test SM4 CBC Encrypt & Decrypt");
		cipher = sm4.sm4_encrypt(CGCipher.PKCS_PADDING, input, keys, iv);
		if(cipher == null){
			System.out.println("SM4 CBC Encrypt Faild");
			return;
		}
		System.out.println(cipher.length + " bytes cipher:" + DatatypeConverter.printHexBinary(cipher));
		
		plain = sm4.sm4_decrypt(CGCipher.PKCS_PADDING, cipher, keys, iv);
		if(plain == null){
			System.out.println("SM4 CBC Decrypt Faild");
			return;
		}
		System.out.println(plain.length + " bytes plain:" + DatatypeConverter.printHexBinary(plain));
		System.out.println("SM4 CBC Encrypt & Decrypt Test SUCCESS");
		System.out.println("=================================================================\n");
		
		
		sm4 = CGCipher.getInstance("sm4", "ofb");
		System.out.println("Test SM4 OFB Encrypt & Decrypt");
		cipher = sm4.sm4_encrypt(CGCipher.PKCS_PADDING, input, keys, iv);
		if(cipher == null){
			System.out.println("SM4 OFB Encrypt Faild");
			return;
		}
		System.out.println(cipher.length + " bytes cipher:" + DatatypeConverter.printHexBinary(cipher));
		
		plain = sm4.sm4_decrypt(CGCipher.PKCS_PADDING, cipher, keys, iv);
		if(plain == null){
			System.out.println("SM4 OFB Decrypt Faild");
			return;
		}
		System.out.println(plain.length + " bytes plain:" + DatatypeConverter.printHexBinary(plain));
		System.out.println("SM4 OFB Encrypt & Decrypt Test SUCCESS");
		System.out.println("=================================================================\n");
		
		
		sm4 = CGCipher.getInstance("sm4", "gcm");
		cipher = new byte[input.length];
		byte[] tag = new byte[16];
		System.out.println("Test SM4 GCM Encrypt & Decrypt");
		byte[] out = sm4.sm4_gcm_encrypt(input, keys, iv, aad);
		if(out == null){
			System.out.println("SM4 GCM Encrypt Faild");
			return;
		}
		cipher = Arrays.copyOfRange(out, 0, cipher.length);
		tag = Arrays.copyOfRange(out, cipher.length, out.length);
		System.out.println(tag.length + " bytes tag:" + DatatypeConverter.printHexBinary(tag));
		System.out.println(cipher.length + " bytes cipher:" + DatatypeConverter.printHexBinary(cipher));
		
		plain = sm4.sm4_gcm_decrypt(out, keys, iv, aad);
		if(plain == null){
			System.out.println("SM4 GCM Decrypt Faild");
			return;
		}
		System.out.println(plain.length + " bytes plain:" + DatatypeConverter.printHexBinary(plain));
		System.out.println("SM4 GCM Encrypt & Decrypt Test SUCCESS");
		System.out.println("=================================================================\n");
	}
}
